// child_process子进程
const { exec, execSync, spawn, spawnSync, execFile, execFileSync, fork } = require("child_process")
const path = require('node:path')
// 有Sync是同步方法，没有就是异步方法
// 异步方法 会返回 回调函数 再返回 buffer ，可以执行shell命令，或者根软件交互
// 1、exec 执行shell命令
// 2、execSync 同步
//    这两个作用：执行较小的shell命令，想要立马拿到结果的shell,可以用execSync, exec有字节上限 200kb, 超出报错
//               根软件交互
// exec('node -v', (err, stdout, stderr) => {  // 回调函数的参数(错误信息，成功返回的流，失败返回的流)
//   if(err) {
//     return err;
//   }
//   console.log(stdout.toString());
// })
// const nodeVersion = execSync('node -v');   // 拿到一个流
// console.log(nodeVersion.toString());
// execSync('start chrome https://baidu.com')   // 使用浏览器打开百度， ---> 跟软件交互
// execSync('F:\\music\\QQMusic\\QQMusic.exe')   // 打开本地应用（需要获取位置）， ---> 跟软件交互

// 3.spawn   没有字节上限的，因为返回的是个流，实时返回的
// 4.spawnSync 用的比较少
// 比如：const a = execSync('netstat')  // netstat命令用于显示网络相关信息（网络套接字）：网络连接、路由表、接口状态等等 
// console.log(a)   执行以上命令会等这个命令执行完成，在得到返回前会一直卡着（等待）,如果超过200kb会返回错误
// 这时就应该用 spawn 了
// const {stdout} = spawn('netstat')    // 输出的是流
// const {stdout} = spawn('netstat', ['-a'])    // 还有第二个参数，是用来写跟在命令后的参数的   netstat -a
// stdout.on('data', (msg) => {        // 监听，实时返回数据
//     console.log(msg.toString());    // 边执行边打印
// })
// stdout.on('close', () => {
//     console.log('结束');
// })

// spawn和exec都有第三个参数 options ，例
/*
spawn('netstat', ['-a'], {
    // options
    // cwd <string> 子进程的当前工作目录。  常用
    // env <Object> 环境变量键值对。
    // encoding <string> 默认为 'utf8'。
    // shell <string> 用于执行命令的 shell。 在 UNIX 上默认为 '/bin/sh'，在 Windows 上默认为 process.env.ComSpec。 
    // timeout <number> 默认为 0。
    // maxBuffer <number> stdout 或 stderr 允许的最大字节数。 默认为 200*1024。 如果超过限制，则子进程会被终止。 查看警告： maxBuffer and Unicode。
    // killSignal <string> | <integer> 默认为 'SIGTERM'。
    // uid <number> 设置该进程的用户标识。
    // gid <number> 设置该进程的组标识。
})
*/

// 5.execFile         作用：执行可执行文件的 .sh 、  .cmd  、  .bat等文件
// 6.execFileSync
// 例： 在cmd文件中写入
/*
echo '开始'           // 在控制台输出 开始
mkdir test           // 创建文件夹
cd ./test
echo console.log("test123123") >test.js         // 输出 console.log("test123123")这一行代码到test.js文件中（没有就新建）
echo '结束'
node test.js                               // 运行test.js文件
*/
// execFile(path.resolve(process.cwd(), './cmd/bat.cmd'), null, (err, stdout) => {   // 在 cjs环境下 process.cwd() 可以用 __dirname代替
//     console.log(stdout.toString());
// })
// 底层实现顺序
// exec -> execFile -> spawn   // exec底层是通过execFile实现 execFile底层通过spawn实现

// 7.fork  只能接受js模块， 帮js创建子进程的， 作用： 当有一些耗时的程序需要执行，又不能阻塞当前线程，可以交给子进程运行，运行完再给出结果
const testProcess = fork('./test.js')  // test.js就是子进程了， 当前js文件就是主进程
testProcess.send('我是主进程')    // 父子进程的通信，发送消息，在test.js中可以接收
process.on('message', (msg) => {
    console.log("收到消息：", msg);
})
// fork 底层使用的是IPC通道进行通讯的， IPC是基于libuv的，libuv是根据操作系统调用不同的指令（windows-->named pipe 管道）（posix --> unix domain socket 套接字）
